import java_cup.runtime.*;

%%



%xstate single_comment multi_comment
%class scanner
%cup
%line
%column
%unicode

nl 			= \n|\r|\r\n
ignored		= " " | \t | {nl}
register	= R([12]?[0-9]|3[01])
integer 	= ("+"|"-")?(0|[1-9]+[0-9]*)
separator	= ","
eol			= ";"


%%

/*single line comment removal*/
"//" 				{ yybegin(single_comment); }
<single_comment>.		{ ; }
<single_comment>{nl}		{ yybegin(YYINITIAL); }

/*multi line comment removal*/
"/*"					{ yybegin(multi_comment); }
<multi_comment>.		{ ; }
<multi_comment>{nl}		{ ; }
<multi_comment><<EOF>>	{ System.out.println("Warning: End-Of-File in comment"); return new Symbol(sym.EOF); }
<multi_comment>"*/"		{ yybegin(YYINITIAL); }

/*syntax rules*/
{ignored}				{ ; }
{register}				{ if (Main.verbosity > 3) System.out.println("-------- + scanner - register found");
						return new Symbol(sym.REG, yyline, yycolumn, new String(yytext())); }
{integer}				{ if (Main.verbosity > 3) System.out.println("-------- + scanner - integer found");
						if( Integer.valueOf(yytext()).intValue() > 65535 )
							System.out.println("Warning: integer overflow detected; using 65535 instead");
						return new Symbol(sym.INT, yyline, yycolumn, new Integer(yytext()));}
{separator}				{ if (Main.verbosity > 3) System.out.println("-------- + scanner - separator found"); 		return new Symbol(sym.COMA); }
{eol}					{ if (Main.verbosity > 3) System.out.println("-------- + scanner - end-of-line found");		return new Symbol(sym.EOL); }


/*symbols*/
NOP	{ if (Main.verbosity > 2) System.out.println("-----# Scanner: NOP operation detected"); return new Symbol(sym.OP_NOP, yyline, yycolumn, new String(yytext()));}
MOV	{ if (Main.verbosity > 2) System.out.println("-----# Scanner: MOV operation detected"); return new Symbol(sym.OP_MOV, yyline, yycolumn, new String(yytext())); }
ADD(U|S) { if (Main.verbosity > 2) System.out.println("-----# Scanner: ADD operation detected");	
							if (yycharat(3)=='U')
								return new Symbol(sym.OP_ADDU, yyline, yycolumn, new String(yytext()));
							else
								return new Symbol(sym.OP_ADDS, yyline, yycolumn, new String(yytext())); }
SUB(U|S) 				{ if (Main.verbosity > 2) System.out.println("-----# Scanner: SUB operation detected"); 
							if (yycharat(3)=='U')
								return new Symbol(sym.OP_SUBU, yyline, yycolumn, new String(yytext()));
							else
								return new Symbol(sym.OP_SUBS, yyline, yycolumn, new String(yytext())); }
MUL(U|S)  				{ if (Main.verbosity > 2) System.out.println("-----# Scanner: MUL operation detected"); 
							if (yycharat(3)=='U')
								return new Symbol(sym.OP_MULU, yyline, yycolumn, new String(yytext()));
							else
								return new Symbol(sym.OP_MULS, yyline, yycolumn, new String(yytext())); }
DIV(U|S) 				{ if (Main.verbosity > 2) System.out.println("-----# Scanner: DIV operation detected");
							if (yycharat(3)=='U')
								return new Symbol(sym.OP_DIVU, yyline, yycolumn, new String(yytext()));
							else
								return new Symbol(sym.OP_DIVS, yyline, yycolumn, new String(yytext())); }
AND 					{ if (Main.verbosity > 2) System.out.println("-----# Scanner: AND operation detected"); return new Symbol(sym.OP_AND, yyline, yycolumn, new String(yytext()));}
OR	 					{ if (Main.verbosity > 2) System.out.println("-----# Scanner: OR operation detected");  return new Symbol(sym.OP_OR, yyline, yycolumn, new String(yytext()));}
XOR  					{ if (Main.verbosity > 2) System.out.println("-----# Scanner: XOR operation detected"); return new Symbol(sym.OP_XOR, yyline, yycolumn, new String(yytext()));}
LD(32|16|8) 			{ if (Main.verbosity > 2) System.out.println("-----# Scanner: LOAD operation detected"); 
							if (yycharat(2)=='3')
								return new Symbol(sym.OP_LD32, yyline, yycolumn, new String(yytext()));
							if (yycharat(2)=='1')
								return new Symbol(sym.OP_LD16, yyline, yycolumn, new String(yytext()));
							if (yycharat(2)=='8')
								return new Symbol(sym.OP_LD8, yyline, yycolumn, new String(yytext()));  }
ST(32|16|8) 			{ if (Main.verbosity > 2) System.out.println("-----# Scanner: STORE operation detected"); 
							if (yycharat(2)=='3')
								return new Symbol(sym.OP_ST32, yyline, yycolumn, new String(yytext()));
							if (yycharat(2)=='1')
								return new Symbol(sym.OP_ST16, yyline, yycolumn, new String(yytext()));
							if (yycharat(2)=='8')
								return new Symbol(sym.OP_ST8, yyline, yycolumn, new String(yytext()));  }
JMP 					{ if (Main.verbosity > 2) System.out.println("-----# Scanner: JUMP operation detected"); return new Symbol(sym.OP_JMP, yyline, yycolumn, new String(yytext()));}
JAL 					{ if (Main.verbosity > 2) System.out.println("-----# Scanner: JUMP and LINK operation detected"); return new Symbol(sym.OP_JAL, yyline, yycolumn, new String(yytext()));}
J(N|L|G|LE|GE)?Z		{ if (Main.verbosity > 2) System.out.println("-----# Scanner: BRANCH operation detected"); 
							if (yycharat(1)=='Z')
								return new Symbol(sym.OP_JZ, yyline, yycolumn, new String(yytext()));
							if (yycharat(1)=='N')
								return new Symbol(sym.OP_JNZ, yyline, yycolumn, new String(yytext()));
							if (yycharat(1)=='L')
								if (yycharat(2)=='E')
									return new Symbol(sym.OP_JLEZ, yyline, yycolumn, new String(yytext()));
								else
									return new Symbol(sym.OP_JLZ, yyline, yycolumn, new String(yytext()));
							if (yycharat(1)=='G')
								if (yycharat(2)=='E')
									return new Symbol(sym.OP_JGEZ, yyline, yycolumn, new String(yytext()));
								else
									return new Symbol(sym.OP_JGZ, yyline, yycolumn, new String(yytext()));  }
(A|L)(L|R)S  			{ if (Main.verbosity > 2) System.out.println("-----# Scanner: SHIFT operation detected"); 
							if (yycharat(0)=='A')
								if (yycharat(1)=='L')
									return new Symbol(sym.OP_ALS, yyline, yycolumn, new String(yytext()));
								else
									return new Symbol(sym.OP_ARS, yyline, yycolumn, new String(yytext()));
							else
								if (yycharat(1)=='L')
									return new Symbol(sym.OP_LLS, yyline, yycolumn, new String(yytext()));
								else
									return new Symbol(sym.OP_LRS, yyline, yycolumn, new String(yytext()));  }
(L|R)R  				{ if (Main.verbosity > 2) System.out.println("-----# Scanner: ROTATE operation detected");
							if (yycharat(0)=='L')
								return new Symbol(sym.OP_LR, yyline, yycolumn, new String(yytext()));
							else
								return new Symbol(sym.OP_RR, yyline, yycolumn, new String(yytext()));  }




[^" ",;\n\/\/]* 		{  System.out.println("Scanner: Entering error state because of " + yytext());
					             return new Symbol(sym.ERR_TOK, yyline, yycolumn, new String(yytext())); 
			   		   }
